home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / machack / Hacks96 / WhenInRome.sit / When In Rome / INIT.c next >
C/C++ Source or Header  |  1996-06-22  |  3KB  |  161 lines

  1. // When In Rome
  2. // Mac Hack XI - MCMXCVI
  3. // Barry Semo 
  4. // barrys@netcom.com
  5.  
  6. #include "A4Stuff.h"
  7. #include "SetupA4.h"
  8. #include <LString.h>
  9.  
  10. typedef pascal void (*DrawStringProc)(ConstStr255Param s);
  11. typedef pascal short (*StringWidthProc)(ConstStr255Param s);
  12.  
  13. pascal void DrawStringPatch(ConstStr255Param s);
  14. pascal short StringWidthPatch(ConstStr255Param s);
  15.  
  16. Boolean IsDigit(char c);
  17. void ToRoman(long decimal, Str255 roman);
  18. void ParseString(Str255 string);
  19.  
  20. DrawStringProc gOldDrawStringAddr;
  21. StringWidthProc gOldStringWidthAddr;
  22.  
  23. Str15 gSymbols[] = {"\pM", "\pCM", "\pD", "\pCD", "\pC", "\pXC", "\pL", 
  24.                         "\pXL", "\pX", "\pIX", "\pV", "\pIV", "\pI"};
  25. short gValue[13] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
  26.  
  27. void main(void)
  28. {
  29. long oldA4;
  30. Handle h;
  31.  
  32. // a4 world
  33. oldA4 = SetCurrentA4();
  34. RememberA4();
  35.  
  36. // detach init resource
  37. h = Get1Resource('INIT', 0);
  38. if (h) DetachResource(h);
  39.     
  40. // initialize
  41. gOldDrawStringAddr = 0L;
  42.     
  43. // patch
  44. gOldDrawStringAddr = (DrawStringProc)GetToolTrapAddress(_DrawString);
  45. SetToolTrapAddress((UniversalProcPtr)DrawStringPatch, _DrawString);
  46.  
  47. gOldStringWidthAddr = (StringWidthProc)GetToolTrapAddress(_StringWidth);
  48. SetToolTrapAddress((UniversalProcPtr)StringWidthPatch, _StringWidth);
  49.     
  50. // restore a4
  51. SetA4(oldA4);
  52. }
  53.  
  54. // DrawString patch that converts a number to roman numeral equivalents
  55. pascal void DrawStringPatch(ConstStr255Param s)
  56. {
  57. long oldA4;
  58. LStr255 decimalNumber;
  59. Str255 tempString;
  60.  
  61. oldA4 = SetUpA4();
  62.  
  63. LString::CopyPStr(s, tempString);//tempCopy
  64. ParseString(tempString);
  65. gOldDrawStringAddr(tempString);
  66.  
  67. RestoreA4(oldA4);
  68. }
  69.  
  70. // StringWidth patch that returns the width of a converted string
  71. pascal short StringWidthPatch(ConstStr255Param s)
  72. {
  73. long oldA4;
  74. LStr255 decimalNumber;
  75. Str255 tempString;
  76. short width;
  77.  
  78. oldA4 = SetUpA4();
  79.  
  80. LString::CopyPStr(s, tempString);//temp copy
  81. ParseString(tempString);
  82. width = gOldStringWidthAddr(tempString);
  83.  
  84. RestoreA4(oldA4);
  85.  
  86. return width;
  87. }
  88.  
  89. // return if a char is a digit 0-9
  90. Boolean IsDigit(char c)
  91. {
  92. return (c >= '0') && (c <= '9');
  93. }
  94.  
  95. void ToRoman(long decimal, Str255 roman)
  96. {
  97. short i=0;
  98. LStr255 destStr;
  99.  
  100. //convert to roman, reducing number by largest roman numeral first,
  101. //working downward
  102. while (decimal > 0) {
  103.     if (gValue[i] <= decimal)
  104.         {
  105.         destStr += gSymbols[i];
  106.         decimal -= gValue[i];
  107.            }
  108.     else
  109.         i++;
  110.     }
  111.  
  112. //copy it back
  113. LString::CopyPStr(destStr, roman);
  114. }
  115.  
  116. // parse a string for embedde numbers, converting them to roman numerals, and
  117. // regParseStringenerating the string
  118. void ParseString(Str255 string)
  119. {
  120. LStr255 destStr("\p");
  121. Str255 romanNum;
  122. long currentNum = 0L;
  123. short length = string[0];
  124. short i;
  125. Boolean seenDigit = false;
  126.  
  127. for (i= 1; i<= length; i++)
  128.     {
  129.     if (IsDigit(string[i]))
  130.         {
  131.         seenDigit = true;
  132.         currentNum = (currentNum*10) + (string[i]-'0');//accumulate number
  133.         }
  134.     else//not a digit
  135.         if (seenDigit)//just terminated a number
  136.             {
  137.             ToRoman(currentNum, romanNum);
  138.  
  139.             destStr += romanNum;
  140.             destStr += string[i];
  141.  
  142.             //reset for next time
  143.             seenDigit = false;
  144.             currentNum = 0L;
  145.             }
  146.         else
  147.             destStr += string[i];
  148.     }
  149.  
  150. // if a number was being accumulated, terminate it
  151. if (currentNum != 0L)
  152.     {
  153.     ToRoman(currentNum, romanNum);
  154.     destStr += romanNum;
  155.     }
  156.  
  157. // copy back to parameter passed in
  158. LString::CopyPStr(destStr, string);
  159. }
  160.  
  161.